package com.bocloud.cmp.service.stats;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import com.alibaba.fastjson.JSONObject;
import com.bocloud.cmp.dao.AlarmDao;
import com.bocloud.cmp.dao.CloudServerDao;
import com.bocloud.cmp.dao.CloudVendorDao;
import com.bocloud.cmp.dao.ClusterDao;
import com.bocloud.cmp.dao.DataStoreDao;
import com.bocloud.cmp.dao.HostSystemDao;
import com.bocloud.cmp.dao.ImageDao;
import com.bocloud.cmp.dao.NetworkDao;
import com.bocloud.cmp.dao.SnapshotDao;
import com.bocloud.cmp.dao.VdcDao;
import com.bocloud.cmp.dao.VolumeDao;
import com.bocloud.cmp.entity.resource.Alarm;
import com.bocloud.cmp.entity.resource.CloudServer;
import com.bocloud.cmp.entity.resource.CloudVendor;
import com.bocloud.cmp.entity.resource.HostSystem;
import com.bocloud.cmp.enums.VendorType;
import com.bocloud.cmp.interfaces.stats.PlatformService;
import com.bocloud.cmp.service.model.ExportModel;
import com.bocloud.cmp.service.model.OpenstackAbstract;
import com.bocloud.cmp.service.model.PlatformAbstract;
import com.bocloud.cmp.service.model.VmwareAbstract;
import com.bocloud.common.model.BsmResult;
import com.bocloud.common.model.GridBean;
import com.bocloud.common.model.Param;
import com.bocloud.common.model.Sign;
import com.bocloud.common.utils.Common;
import com.bocloud.common.utils.GridHelper;
import com.bocloud.common.utils.MapTools;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;

@Service("platformService")
public class PlatformServiceImpl implements PlatformService {

	private Logger logger = LoggerFactory.getLogger(PlatformServiceImpl.class);
	@Autowired
	private VdcDao vdcDao;
	@Autowired
	private ClusterDao clusterDao;
	@Autowired
	private HostSystemDao hostSystemDao;
	@Autowired
	private CloudServerDao cloudServerDao;
	@Autowired
	private SnapshotDao snapshotDao;
	@Autowired
	private NetworkDao networkDao;
	@Autowired
	private DataStoreDao dataStoreDao;
	@Autowired
	private VolumeDao volumeDao;
	@Autowired
	private ImageDao imageDao;
	@Autowired
	private AlarmDao alarmDao;
	@Autowired
	private CloudVendorDao cloudVendorDao;

	@Override
	public BsmResult getAbstracts(String params) {
		JSONObject object = JSONObject.parseObject(params);
		BsmResult result = null;
		try {
			Long vendorId = null;
			String type = null;
			if (null != object) {
				vendorId = object.getLong("vendorId");
				type = object.getString("type");
			}
			VendorType vendorType = null;
			if (null == vendorId && StringUtils.isEmpty(type)) {
				OpenstackAbstract openstack = getOpenstack(null);
				VmwareAbstract vmware = getVmware(null);
				return new BsmResult(true, new PlatformAbstract(openstack, vmware), "获取信息成功");
			} else if (null != vendorId && StringUtils.isEmpty(type)) {
				CloudVendor vendor = cloudVendorDao.query(vendorId);
				vendorType = VendorType.valueOf(vendor.getType());
			} else {
				vendorType = VendorType.valueOf(type);
			}
			switch (vendorType) {
			case OPENSTACK:
				OpenstackAbstract openstack = getOpenstack(vendorId);
				result = new BsmResult(true, new PlatformAbstract(openstack, null), "获取信息成功");
				break;
			case VMWARE:
				VmwareAbstract vmware = getVmware(vendorId);
				result = new BsmResult(true, new PlatformAbstract(null, vmware), "获取信息成功");
				break;
			default:
				result = new BsmResult(false, "暂不支持该类型平台");
				break;
			}
		} catch (Exception e) {
			logger.error("get platform abstracts error:", e);
			return new BsmResult(false, "获取信息失败");
		}
		return result;
	}

	private OpenstackAbstract getOpenstack(Long vendorId) throws Exception {
		List<Param> params = Lists.newArrayList();
		if (null != vendorId) {
			params.add(new Param(MapTools.simpleMap("vendorId", vendorId), Sign.EQ));
		}
		int hosts = hostSystemDao.count(params, VendorType.OPENSTACK.name());
		int networks = networkDao.count(params, VendorType.OPENSTACK.name());
		int snapshots = snapshotDao.count(params, VendorType.OPENSTACK.name());
		int volumes = volumeDao.count(params);
		int images = imageDao.count(params);
		int alarms = alarmDao.count(params, VendorType.OPENSTACK.name());
		int cpus = 0; // cpu数量
		int mems = 0; // 内存数量
		int disks = 0; // 磁盘数量
		List<HostSystem> hostSystems = hostSystemDao.list(vendorId, VendorType.OPENSTACK.name());
		for (HostSystem hostSystem : hostSystems) {
			cpus += hostSystem.getCpuNum();
			mems += hostSystem.getMemTotal();
			disks += hostSystem.getDiskTotal();
		}
		int instances = cloudServerDao.count(params, VendorType.OPENSTACK.name());
		params.add(new Param(MapTools.simpleMap("isTemplate", 1), Sign.EQ));
		int templates = cloudServerDao.count(params, VendorType.OPENSTACK.name());
		int servers = instances - templates;
		return new OpenstackAbstract(hosts, servers, templates, snapshots, networks, volumes, images, cpus, mems, disks,
				alarms);
	}

	private VmwareAbstract getVmware(Long vendorId) throws Exception {
		List<Param> params = Lists.newArrayList();
		if (null != vendorId) {
			params.add(new Param(MapTools.simpleMap("vendorId", vendorId), Sign.EQ));
		}
		int centers = vdcDao.count(params);
		int clusters = clusterDao.count(params);
		int hosts = hostSystemDao.count(params, VendorType.VMWARE.name());
		int networks = networkDao.count(params, VendorType.VMWARE.name());
		int snapshots = snapshotDao.count(params, VendorType.VMWARE.name());
		int stores = dataStoreDao.count(params);
		int alarms = alarmDao.count(params, VendorType.VMWARE.name());
		int cpus = 0; // cpu数量
		int mems = 0; // 内存数量
		int disks = 0; // 磁盘数量
		// 通过每台宿主机得到所有的cpu、内存、磁盘信息
		List<HostSystem> hostSystems = hostSystemDao.list(vendorId, VendorType.VMWARE.name());
		for (HostSystem hostSystem : hostSystems) {
			cpus += hostSystem.getCpuNum();
			mems += hostSystem.getMemTotal();
			disks += hostSystem.getDiskTotal();
		}
		int instances = cloudServerDao.count(params, VendorType.VMWARE.name());
		params.add(new Param(MapTools.simpleMap("isTemplate", 1), Sign.EQ));
		int templates = cloudServerDao.count(params, VendorType.VMWARE.name());
		int servers = instances - templates;
		return new VmwareAbstract(centers, clusters, hosts, servers, templates, snapshots, networks, stores, cpus, mems,
				disks, alarms);
	}

	@Override
	public BsmResult getHosts(int page, int rows, List<Param> params, Map<String, String> sorter, String type) {
		try {
			if (null == params) {
				params = Lists.newArrayList();
			}
			if (null == sorter) {
				sorter = Maps.newHashMap();
			}
			sorter.put("gmtCreate", Common.ONE);
			int total = this.hostSystemDao.count(params, type);
			List<HostSystem> list = this.hostSystemDao.list(page, rows, params, sorter, type);
			GridBean gridBean = GridHelper.getBean(page, rows, total, list);
			return new BsmResult(true, gridBean, "查询成功");
		} catch (Exception e) {
			logger.error("Query host list fail:", e);
			return new BsmResult(false, "查询失败");
		}
	}

	@Override
	public BsmResult getAlarms(int page, int rows, List<Param> params, Map<String, String> sorter, String type) {
		try {
			if (null == params) {
				params = new ArrayList<>();
			}
			if (null == sorter) {
				sorter = Maps.newHashMap();
			}
			sorter.put("gmtCreate", Common.ONE);
			int total = this.alarmDao.count(params, type);
			List<Alarm> list = this.alarmDao.list(page, rows, params, sorter, type);
			GridBean gridBean = GridHelper.getBean(page, rows, total, list);
			return new BsmResult(true, gridBean, "查询成功");
		} catch (Exception e) {
			logger.error("List alarm fail:", e);
			return new BsmResult(false, "查询失败");
		}
	}

	@Override
	public BsmResult export(String params) {
		JSONObject object = JSONObject.parseObject(params);
		BsmResult result = null;
		try {
			ExportModel model = new ExportModel();

			Long vendorId = null;
			String type = null;
			if (null != object) {
				vendorId = object.getLong("vendorId");
				type = object.getString("type");
			}
			PlatformAbstract plateFormAbstract = new PlatformAbstract();
			VendorType vendorType = null;
			List<Param> paramList = Lists.newArrayList();
			if (null == vendorId && StringUtils.isEmpty(type)) {
				// 导出全部
				plateFormAbstract.setOpenstack(getOpenstack(null));// 获取openstack平台下统计数据
				plateFormAbstract.setVmware(getVmware(null));// 获取vmware平台下统计数据
				model.setType("ALL");
			} else if (null != vendorId && StringUtils.isEmpty(type)) {
				CloudVendor vendor = cloudVendorDao.query(vendorId);
				vendorType = VendorType.valueOf(vendor.getType());
			} else {
				vendorType = VendorType.valueOf(type);
			}

			if (null != vendorType) {
				switch (vendorType) {
				case OPENSTACK:
					plateFormAbstract.setOpenstack(getOpenstack(vendorId));// 导出openstack概要统计
					model.setType("OPENSTACK");
					break;
				case VMWARE:
					// 导出VMware概要统计
					plateFormAbstract.setVmware(getVmware(vendorId));// 导出VMware概要统计
					model.setType("VMWARE");
					break;
				default:
					result = new BsmResult(false, "暂不支持该类型平台");
					break;
				}
			}

			paramList.clear();
			if (null != vendorId) {
				paramList.add(new Param(MapTools.simpleMap("vendorId", vendorId), Sign.EQ));
			}
			// 获取所有的告警
			List<Alarm> alarms = this.alarmDao.list(1, Integer.MAX_VALUE, paramList, null, type);
			// 获取vmware平台下的所有的物理机
			List<HostSystem> hosts = this.hostSystemDao.list(1, Integer.MAX_VALUE, paramList, null, type);
			for (HostSystem host : hosts) {
				// 获取物理机下所有的虚拟机
				List<CloudServer> servers = cloudServerDao.listByHid(host.getId());
				for (CloudServer cloudServer : servers) {
					paramList.clear();
					paramList.add(new Param(MapTools.simpleMap("vmId", cloudServer.getId()), Sign.EQ));
					cloudServer.setSnapshotCount(snapshotDao.count(paramList));
					cloudServer.setHostName(host.getName());
				}
				host.setServers(servers);

				paramList.clear();
				paramList.add(new Param(MapTools.simpleMap("hostId", host.getId()), Sign.EQ));
				int vmNum = cloudServerDao.count(paramList);
				paramList.add(new Param(MapTools.simpleMap("isTemplate", 1), Sign.EQ));
				int templateNum = cloudServerDao.count(paramList);
				host.setVmNum(vmNum - templateNum);
				host.setTemplateNum(templateNum);
			}
			model.setPlateFormAbstract(plateFormAbstract);
			model.setHosts(hosts);
			model.setAlarms(alarms);
			result = new BsmResult(true, model, "查询平台数据成功");
		} catch (Exception e) {
			logger.error("export platform data report error:", e);
			return new BsmResult(false, "导出报表数据失败");
		}
		return result;
	}
}